from enum import Enum

# 定义非终结符、终结符
class NonTerminal(Enum):
    OPTIONAL_WHERE_CLAUSE = "option_where_clause"
    PROGRAM = "program"
    STMT_LIST = "stmt_list"
    STMT = "stmt"
    SELECT_STMT = "select_stmt"
    CREATE_TABLE_STMT = "create_table_stmt"
    INSERT_STMT = "insert_stmt"
    DELETE_STMT = "delete_stmt"
    UPDATE_STMT = "update_stmt"
    UPDATE_CORE = "update_core"
    SET_LIST = "set_list"
    SET_LIST_TAIL = "set_list_tail"
    ASSIGNMENT = "assignment"
    TARGET_LIST = "target_list"
    TARGET_LIST_TAIL = "target_list_tail"
    TABLE_NAME = "table_name"
    COL_DEF_LIST = "col_def_list"
    COL_DEF_LIST_TAIL = "col_def_list_tail"
    COL_DEF = "col_def"
    DATA_TYPE = "data_type"
    VAL_LIST = "val_list"
    VAL_LIST_TAIL = "val_list_tail"
    VALUE = "value"
    CONDITION = "condition"
    EXPR = "expr"
    EXPR_TAIL = "expr_tail"
    TERM = "term"
    TERM_TAIL = "term_tail"
    FACTOR = "factor"
    COMP_OP = "comp_op"
    WHERE_CLAUSE = "where_clause"
    SELECT_CORE = "select_core"
    DELETE_CORE = "delete_core"

class Terminal(Enum):
    SELECT = "SELECT"
    FROM = "FROM"
    WHERE = "WHERE"
    CREATE = "CREATE"
    TABLE = "TABLE"
    INSERT = "INSERT"
    INTO = "INTO"
    VALUES = "VALUES"
    UPDATE = "UPDATE"
    SET = "SET"
    DELETE = "DELETE"
    INTEGER = "INTEGER"
    VARCHAR = "VARCHAR"
    FLOAT = "FLOAT"
    BOOLEAN = "BOOLEAN"
    Date = "DATE"
    ASTERISK = "*"
    COMMA = ","
    SEMICOLON = ";"
    LPAREN = "("
    RPAREN = ")"
    EQ = "="
    GT = ">"
    LT = "<"
    GE = ">="
    LE = "<="
    NE = "!="
    AND = "AND"
    OR = "OR"
    NOT = "NOT"
    PLUS = "+"
    MINUS = "-"
    MUL = "*"
    DIV = "/"
    NUMBER = "NUMBER"
    STRING = "STRING"
    IDENTIFIER = "IDENTIFIER"
    EOF = "EOF"
    EPSILON = "ε"
    IS="IS"
    IN="IN"

# 消除左递归后的文法产生式
PRODUCTIONS = {
    NonTerminal.PROGRAM: [
        [NonTerminal.STMT_LIST, Terminal.EOF]
    ],
    NonTerminal.STMT_LIST: [
        [NonTerminal.STMT, Terminal.SEMICOLON, NonTerminal.STMT_LIST],
        [Terminal.EPSILON]
    ],
    # 语句类型
    NonTerminal.STMT: [
        [NonTerminal.SELECT_STMT],
        [NonTerminal.CREATE_TABLE_STMT],
        [NonTerminal.INSERT_STMT],
        [NonTerminal.DELETE_STMT],
        [NonTerminal.UPDATE_STMT]
    ],
    # select语句
    NonTerminal.SELECT_STMT: [
        [NonTerminal.SELECT_CORE, NonTerminal.OPTIONAL_WHERE_CLAUSE]
    ],
    NonTerminal.OPTIONAL_WHERE_CLAUSE: [
        [NonTerminal.WHERE_CLAUSE],
        [Terminal.EPSILON]
    ],
    NonTerminal.SELECT_CORE: [
        [Terminal.SELECT, NonTerminal.TARGET_LIST, Terminal.FROM, NonTerminal.TABLE_NAME]
    ],

    NonTerminal.WHERE_CLAUSE: [
        [Terminal.WHERE, NonTerminal.CONDITION]
    ],
    # select要选出的列
    NonTerminal.TARGET_LIST: [
        [Terminal.ASTERISK, NonTerminal.TARGET_LIST_TAIL],
        [Terminal.IDENTIFIER, NonTerminal.TARGET_LIST_TAIL]
    ],
    NonTerminal.TARGET_LIST_TAIL: [
        [Terminal.COMMA, Terminal.IDENTIFIER, NonTerminal.TARGET_LIST_TAIL],
        [Terminal.EPSILON]
    ],
    # create table
    NonTerminal.CREATE_TABLE_STMT: [
        [Terminal.CREATE, Terminal.TABLE, NonTerminal.TABLE_NAME, Terminal.LPAREN, NonTerminal.COL_DEF_LIST, Terminal.RPAREN]
    ],
    NonTerminal.COL_DEF_LIST: [
        [NonTerminal.COL_DEF, NonTerminal.COL_DEF_LIST_TAIL]
    ],
    NonTerminal.COL_DEF_LIST_TAIL: [
        [Terminal.COMMA, NonTerminal.COL_DEF, NonTerminal.COL_DEF_LIST_TAIL],
        [Terminal.EPSILON]
    ],
    NonTerminal.COL_DEF: [
        [Terminal.IDENTIFIER, NonTerminal.DATA_TYPE]
    ],
    NonTerminal.DATA_TYPE: [
        [Terminal.INTEGER],
        [Terminal.VARCHAR],
        [Terminal.FLOAT],
        [Terminal.BOOLEAN],
        [Terminal.Date]
    ],
    # insert
    NonTerminal.INSERT_STMT: [
        [Terminal.INSERT, Terminal.INTO, NonTerminal.TABLE_NAME, Terminal.LPAREN, NonTerminal.TARGET_LIST, Terminal.RPAREN, Terminal.VALUES, Terminal.LPAREN, NonTerminal.VAL_LIST, Terminal.RPAREN]
    ],
    NonTerminal.VAL_LIST: [
        [NonTerminal.VALUE, NonTerminal.VAL_LIST_TAIL]
    ],
    NonTerminal.VAL_LIST_TAIL: [
        [Terminal.COMMA, NonTerminal.VALUE, NonTerminal.VAL_LIST_TAIL],
        [Terminal.EPSILON]
    ],
    NonTerminal.VALUE: [
        [Terminal.NUMBER],
        [Terminal.STRING]
    ],
    # delete
    NonTerminal.DELETE_STMT: [
        [NonTerminal.DELETE_CORE, NonTerminal.OPTIONAL_WHERE_CLAUSE]
    ],
    NonTerminal.DELETE_CORE: [
        [Terminal.DELETE, Terminal.FROM, NonTerminal.TABLE_NAME]
    ],
    # update
    NonTerminal.UPDATE_STMT: [
        [NonTerminal.UPDATE_CORE, NonTerminal.OPTIONAL_WHERE_CLAUSE]
    ],
    NonTerminal.UPDATE_CORE: [
        [Terminal.UPDATE, NonTerminal.TABLE_NAME, Terminal.SET, NonTerminal.SET_LIST]
    ],
    NonTerminal.SET_LIST: [
        [NonTerminal.ASSIGNMENT, NonTerminal.SET_LIST_TAIL]
    ],
    NonTerminal.SET_LIST_TAIL: [
        [Terminal.COMMA, NonTerminal.ASSIGNMENT, NonTerminal.SET_LIST_TAIL],
        [Terminal.EPSILON]
    ],
    NonTerminal.ASSIGNMENT: [
        [Terminal.IDENTIFIER, Terminal.EQ, NonTerminal.EXPR]
    ],
    NonTerminal.CONDITION: [
        [NonTerminal.EXPR, NonTerminal.COMP_OP, NonTerminal.EXPR]
    ],
    NonTerminal.COMP_OP: [
        [Terminal.EQ],
        [Terminal.GT],
        [Terminal.LT],
        [Terminal.GE],
        [Terminal.LE],
        [Terminal.NE]
    ],
    # 表达式，包括项和因子
    NonTerminal.EXPR: [
        [NonTerminal.TERM, NonTerminal.EXPR_TAIL]
    ],
    NonTerminal.EXPR_TAIL: [
        [Terminal.PLUS, NonTerminal.TERM, NonTerminal.EXPR_TAIL],
        [Terminal.MINUS, NonTerminal.TERM, NonTerminal.EXPR_TAIL],
        [Terminal.IN, Terminal.LPAREN,NonTerminal.VAL_LIST, Terminal.RPAREN],
        [Terminal.EPSILON]
    ],
    NonTerminal.TERM: [
        [NonTerminal.FACTOR, NonTerminal.TERM_TAIL]
    ],
    NonTerminal.TERM_TAIL: [
        [Terminal.MUL, NonTerminal.FACTOR, NonTerminal.TERM_TAIL],
        [Terminal.DIV, NonTerminal.FACTOR, NonTerminal.TERM_TAIL],
        [Terminal.EPSILON]
    ],
    NonTerminal.FACTOR: [
        [Terminal.NUMBER],
        [Terminal.STRING],
        [Terminal.IDENTIFIER],
        [Terminal.LPAREN, NonTerminal.EXPR, Terminal.RPAREN],
        [Terminal.PLUS, NonTerminal.FACTOR],
        [Terminal.MINUS, NonTerminal.FACTOR]
    ],
    NonTerminal.TABLE_NAME: [
        [Terminal.IDENTIFIER]
    ]
}